// Copyright 2022 a.o.smith ALL Rights Reserved
package com.liuxinlong.modules.standard.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.liuxinlong.common.AosException;
import com.liuxinlong.common.ExcelData;
import com.liuxinlong.common.SnowFlake;
import com.liuxinlong.constant.ThreadLocalConstants;
import com.liuxinlong.enums.ReturnCodes;
import com.liuxinlong.modules.dao.TestClauseDao;
import com.liuxinlong.modules.dao.HierarchyDao;
import com.liuxinlong.modules.dao.StandardClauseRelationDao;
import com.liuxinlong.modules.dao.StandardDao;
import com.liuxinlong.modules.entity.TestClause;
import com.liuxinlong.modules.entity.StandardClauseRelation;
import com.liuxinlong.modules.entity.User;
import com.liuxinlong.modules.standard.service.TestClauseService;
import com.liuxinlong.modules.system.service.FileManageService;
import com.liuxinlong.utils.ExcelUtils;
import com.liuxinlong.utils.ObjectUtils;
import com.liuxinlong.utils.ThreadlocalUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 测试条款service实现
 *
 * @author liuxinlong@hotwater.com.cn
 * @version 1.0.0
 * @since 2022年7月13日
 */
@Service
@Slf4j
public class TestClauseServiceImpl implements TestClauseService {

    @Autowired
    private TestClauseDao testClauseDao;

    @Autowired
    private HierarchyDao hierarchyDao;

    @Autowired
    private FileManageService fileManageService;

    @Autowired
    private StandardClauseRelationDao standardClauseRelationDao;

    @Autowired
    private StandardDao standardDao;

    @Override
    public List<Map<String, Object>> pageClauseInfo(Map<String, Object> queryParam) {
        int startNum = (int) queryParam.get("startNum");
        List<TestClause> originList = testClauseDao.pageClauseList(queryParam);
        return completeResult(originList, startNum);
    }

    @Override
    public int getClauseCount(Map<String, Object> queryParam) {
        return testClauseDao.getClauseCount(queryParam);
    }

    @Override
    @Transactional
    public void addClauseInfo(TestClause testClause, String standardId) {
        String id = SnowFlake.nextIdStr();
        testClause.setId(id);
        String requirementAttach = testClause.getRequirementAttach();
        if (StringUtils.isNotEmpty(requirementAttach)) {
            fileManageService.updateBusinessFile(requirementAttach, id);
        }
        String applicabilityAttach = testClause.getApplicabilityAttach();
        if (StringUtils.isNotEmpty(applicabilityAttach)) {
            fileManageService.updateBusinessFile(applicabilityAttach, id);
        }
        String referenceAttach = testClause.getReferenceAttach();
        if (StringUtils.isNotEmpty(referenceAttach)) {
            fileManageService.updateBusinessFile(referenceAttach, id);
        }
        String attach = testClause.getAttach();
        if (StringUtils.isNotEmpty(attach)) {
            fileManageService.updateBusinessFile(attach, id);
        }
        int current = standardClauseRelationDao.getClauseCount(standardId);
        StandardClauseRelation relation = new StandardClauseRelation();
        relation.setId(SnowFlake.nextIdStr());
        relation.setStandardId(standardId);
        relation.setClauseId(id);
        relation.setCurrentSort(current + 1);
        standardClauseRelationDao.insert(relation);
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        testClause.setCreateUser(currentUser.getId());
        testClauseDao.insert(testClause);
    }

    @Override
    public void updateClauseInfo(TestClause testClause, String standardId) {
        String id = testClause.getId();
        if (StringUtils.isEmpty(id)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，id不存在");
        }
        TestClause oldInfo = testClauseDao.selectById(id);
        if (ObjectUtils.isEmpty(oldInfo)) {
            throw new AosException(ReturnCodes.HTTP_PARAM_ERROR, "参数异常，原设计标准不存在");
        }
        String requirementAttach = testClause.getRequirementAttach();
        fileManageService.updateBusinessFile(requirementAttach, id);
        String applicabilityAttach = testClause.getApplicabilityAttach();
        fileManageService.updateBusinessFile(applicabilityAttach, id);
        String referenceAttach = testClause.getReferenceAttach();
        fileManageService.updateBusinessFile(referenceAttach, id);
        String attach = testClause.getAttach();
        fileManageService.updateBusinessFile(attach, id);
        int current = standardClauseRelationDao.getClauseCount(standardId);
        StandardClauseRelation oldRelation = standardClauseRelationDao.getRelation(standardId, id);
        if (ObjectUtils.isEmpty(oldRelation)) {
            StandardClauseRelation relation = new StandardClauseRelation();
            relation.setId(SnowFlake.nextIdStr());
            relation.setClauseId(id);
            relation.setStandardId(standardId);
            relation.setCurrentSort(current + 1);
            standardClauseRelationDao.insert(relation);
        } else {
            oldRelation.setStandardId(standardId);
            oldRelation.setCurrentSort(current + 1);
            standardClauseRelationDao.updateById(oldRelation);
        }
        User currentUser = (User) ThreadlocalUtils.getCache(ThreadLocalConstants.USER_INFO);
        testClause.setUpdateUser(currentUser.getId());
        testClauseDao.updateById(testClause);
    }

    @Override
    public void deleteClauseInfo(String id) {
        testClauseDao.deleteById(id);
    }

    /**
     * 补全数据
     *
     * @param originList 原始数据
     * @param startNum   起始数
     * @return 补全数据列表
     */
    private List<Map<String, Object>> completeResult(List<TestClause> originList, int startNum) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (ObjectUtil.isEmpty(originList)) {
            return resultList;
        }
        List<String> clauseIds = originList.stream().map(TestClause::getId).collect(Collectors.toList());
        Map<String, Map<String, Object>> relationMap = new HashMap<>();
        if (clauseIds.size() > 0) {
            Map<String, Map<String, String>> standardMap = standardDao.getStandardMap();
            List<StandardClauseRelation> relationList = standardClauseRelationDao.getRelationByClause(clauseIds);
            for (StandardClauseRelation relation : relationList) {
                Map<String, Object> map = ObjectUtils.object2Map(relation);
                if (standardMap.containsKey(relation.getStandardId())) {
                    map.put("standardName", standardMap.get(relation.getStandardId()).get("name"));
                }
                relationMap.put(relation.getClauseId(), map);
            }
        }
        Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
        int sort = startNum + 1;
        for (TestClause item : originList) {
            Map<String, Object> map = ObjectUtils.object2Map(item);
            map.put("sort", sort);
            String hierarchyId = item.getHierarchy();
            if (StringUtils.isNotEmpty(hierarchyId)) {
                Map<String, String> hierarchyInfo = hierarchyMap.get(hierarchyId);
                if (!ObjectUtils.isEmpty(hierarchyInfo)) {
                    map.put("hierarchyName", hierarchyInfo.get("name"));
                }
            }
            if (relationMap.containsKey(item.getId())) {
                map.put("standardId", relationMap.get(item.getId()).get("standardId"));
                map.put("standardName", relationMap.get(item.getId()).get("standardName"));
            }
            resultList.add(map);
            sort++;
        }
        return resultList;
    }

    @Override
    public void exportClauseInfo(String id, HttpServletResponse response) {
        Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
        ExcelData data = new ExcelData();
        data.setFileName("测试条款导出excel.xlsx");
        List<TestClause> clauseList = testClauseDao.getClauseList();
        String[] head = {"序号", "条款编号", "条款名称", "作用层级", "技术要求", "适用范围", "备注"};
        data.setHead(head);
        String[][] dataList = new String[clauseList.size()][head.length];
        int index = 0;
        for (TestClause dc : clauseList) {
            dataList[index][0] = String.valueOf(index + 1);
            dataList[index][1] = dc.getClauseSn();
            dataList[index][2] = dc.getName();
            dataList[index][3] = StringUtils.isNotEmpty(dc.getHierarchy()) ?
                    hierarchyMap.containsKey(dc.getHierarchy()) ? hierarchyMap.get(dc.getHierarchy()).get("name") : "" : "";
            dataList[index][4] = dc.getRequirement();
            dataList[index][5] = dc.getApplicability();
            dataList[index][6] = dc.getRemark();
            index++;
        }
        data.setData(Arrays.asList(dataList));
        ExcelUtils.exportExcel(response, data);

    }

    @Override
    public List<Map<String, Object>> listStandardClause(String standardId) {
        List<StandardClauseRelation> relationList = standardClauseRelationDao.getRelationByStandard(standardId);
        if (relationList.isEmpty()) {
            return new ArrayList<>();
        }
        Map<String, Map<String, String>> hierarchyMap = hierarchyDao.getHierarchyMap();
        List<String> clauseIds = relationList.stream().map(StandardClauseRelation::getClauseId).collect(Collectors.toList());
        List<TestClause> clauseList = testClauseDao.listStandardClause(clauseIds);
        List<Map<String, Object>> resultList = new ArrayList<>(clauseList.size());
        int sort = 1;
        for (TestClause item : clauseList) {
            Map<String, Object> map = ObjectUtils.object2Map(item);
            map.put("sort", sort);
            String hierarchyId = item.getHierarchy();
            if (StringUtils.isNotEmpty(hierarchyId)) {
                Map<String, String> hierarchyInfo = hierarchyMap.get(hierarchyId);
                if (!ObjectUtils.isEmpty(hierarchyInfo)) {
                    map.put("hierarchyName", hierarchyInfo.get("name"));
                }
            }
            resultList.add(map);
        }
        return resultList;
    }
}
